﻿using Quartz;
using Quartz.Impl;
using System;
using System.Threading.Tasks;

namespace Core.Framework.Common
{

    /// <summary>
    /// 计划任务
    /// </summary>
    public class TimerJob
    {
        /// <summary>
        /// 调度器
        /// </summary>
        static IScheduler scheduler;


        public TimerJob()
        {
            Initialization();
        }


        private void Initialization()
        {
            if (null != scheduler)
                return;

            // 创建任务调度工程
            StdSchedulerFactory factory = new StdSchedulerFactory();

            // 创建一个调度器
            scheduler = factory.GetScheduler().Result;

            // 开始调度器
            scheduler.Start();
        }

        /// <summary>
        /// 停止调度器            
        /// </summary>
        public void Stop()
        {
            scheduler.Shutdown();
            scheduler = null;
        }




        /// <summary>
        /// 创建任务指定时间开始
        /// 并发执行
        /// </summary>
        /// <typeparam name="T">任务实体[IJob]</typeparam>
        /// <param name="startTimeUtc">开始时间</param>
        /// <param name="action">间隔时间</param>
        /// <param name="JobDataMap">传参</param>
        /// <returns></returns>
        public void Register<T>(DateTimeOffset startTimeUtc, Action<SimpleScheduleBuilder> action, Action<JobDataMap> JobDataMap = null) where T : ITimerJob, new()
        {

            //创建一个作业
            var job = JobBuilder.Create<Job<T>>().Build();

            if (null != JobDataMap)
                JobDataMap.Invoke(job.JobDataMap);

            //创建一个触发器
            var tigger = TriggerBuilder.Create()
                .StartAt(startTimeUtc)
                .WithSimpleSchedule(action)
                .Build();

            //把作业和触发器放入调度器中
            scheduler.ScheduleJob(job, tigger);

        }

        /// <summary>
        /// 创建任务
        /// 并发执行
        /// </summary>
        /// <typeparam name="T">任务实体[IJob]</typeparam>
        /// <param name="action">间隔时间</param>
        /// <param name="JobDataMap">传参</param>
        /// <returns></returns>
        public void Register<T>(Action<SimpleScheduleBuilder> action, Action<JobDataMap> JobDataMap = null) where T : ITimerJob, new()
        {

            //创建一个作业
            var job = JobBuilder.Create<Job<T>>().Build();

            if (null != JobDataMap)
                JobDataMap.Invoke(job.JobDataMap);

            //创建一个触发器
            var tigger = TriggerBuilder.Create()
                .StartNow()
                .WithSimpleSchedule(action)
                .Build();

            //把作业和触发器放入调度器中
            scheduler.ScheduleJob(job, tigger);
        }



        /// <summary>
        /// 创建任务指定时间开始
        /// 顺序运行
        /// </summary>
        /// <typeparam name="T">任务实体[IJob]</typeparam>
        /// <param name="startTimeUtc">开始时间</param>
        /// <param name="action">间隔时间</param>
        /// <param name="JobDataMap">传参</param>
        /// <returns></returns>
        public void RegisterDisallowConcurrent<T>(DateTimeOffset startTimeUtc, Action<SimpleScheduleBuilder> action, Action<JobDataMap> JobDataMap = null) where T : ITimerJob, new()
        {

            //创建一个作业
            var job = JobBuilder.Create<JobDisallowConcurrent<T>>().Build();

            if (null != JobDataMap)
                JobDataMap.Invoke(job.JobDataMap);

            //创建一个触发器
            var tigger = TriggerBuilder.Create()
                .StartAt(startTimeUtc)
                .WithSimpleSchedule(action)
                .Build();

            //把作业和触发器放入调度器中
            scheduler.ScheduleJob(job, tigger);

        }

        /// <summary>
        /// 创建任务
        /// 顺序运行
        /// </summary>
        /// <typeparam name="T">任务实体[IJob]</typeparam>
        /// <param name="action">间隔时间</param>
        /// <param name="JobDataMap">传参</param>
        /// <returns></returns>
        public void RegisterDisallowConcurrent<T>(Action<SimpleScheduleBuilder> action, Action<JobDataMap> JobDataMap = null) where T : ITimerJob, new()
        {

            //创建一个作业
            var job = JobBuilder.Create<JobDisallowConcurrent<T>>().Build();

            if (null != JobDataMap)
                JobDataMap.Invoke(job.JobDataMap);

            //创建一个触发器
            var tigger = TriggerBuilder.Create()
                .StartNow()
                .WithSimpleSchedule(action)
                .Build();

            //把作业和触发器放入调度器中
            scheduler.ScheduleJob(job, tigger);
        }



    }

    /// <summary>
    /// 顺序执行
    /// </summary>
    /// <typeparam name="T"></typeparam>
    [DisallowConcurrentExecution]
    class JobDisallowConcurrent<T> : IJob
        where T : ITimerJob, new()
    {

        public Task Execute(IJobExecutionContext context)
        {
            return Start(context);
        }

        public async Task Start(IJobExecutionContext context)
        {
            await Task.Run(() => new T().Execute(context));
        }
    }

    /// <summary>
    /// 并发执行
    /// </summary>
    /// <typeparam name="T"></typeparam>
    class Job<T> : IJob
        where T : ITimerJob, new()
    {

        public Task Execute(IJobExecutionContext context)
        {
            return Start(context);
        }

        public async Task Start(IJobExecutionContext context)
        {
            await Task.Run(() => new T().Execute(context));
        }
    }


}
